package de.playmee;

import java.util.HashSet;
import java.util.Set;

import de.playmee.Weather.Condition;
import de.playmee.enums.Mood;
import de.playmee.enums.Release;
import de.playmee.enums.TimeOfDay;

public class Channel {
	
	public static final int NEW_CHANNEL_ID = -1;

	private long id;
	private String label;
	private int image = R.drawable.ic_contact_picture_2; // default art
	
	private int maxDuration;
	private int minBpm;
	
	private Set<Mood> moods = new HashSet<Mood>();
	private Set<Release> releases = new HashSet<Release>();
	
	private boolean considerSeason;
	private boolean considerWeather;
	private boolean considerTimeOfDay;
	
	private Playlist playlist;
	
	public Channel(long id, String label) {
		this.id = id;
		this.label = label;
	}
	
	public Channel(String label) {
		this(NEW_CHANNEL_ID, label);
	}
	
	/**
	 * sets the id
	 * 
	 * @param id
	 */
	public void setId(long id) {
		this.id = id;
	}
	
	/**
	 * sets the label
	 * 
	 * @param label
	 */
	public void setLabel(String label) {
		this.label = label;
	}
	
	/**
	 * sets the image id
	 * 
	 * @param image
	 */
	public void setImage(int image) {
		this.image = image;
	}
	
	/**
	 * sets the duration
	 * 
	 * @param duration
	 */
	public void setDuration(int duration) {
		this.maxDuration = duration;
	}
	
	/**
	 * sets the beats per minute
	 * 
	 * @param bpm
	 */
	public void setBpm(int bpm) {
		this.minBpm = bpm;
	}
	
	/**
	 * sets the playlist
	 * 
	 * @param playlist
	 */
	public void setPlaylist(Playlist playlist) {
		this.playlist = playlist;
	}
	
	/**
	 * @return id
	 */
	public long getId() {
		return id;
	}
	
	/**
	 * @return label
	 */
	public String getLabel() {
		return label;
	}
	
	/**
	 * @return image
	 */
	public int getImage() {
		return image;
	}
	
	/**
	 * @return duration
	 */
	public int getDuration() {
		return maxDuration;
	}
	
	/**
	 * @return bpm
	 */
	public int getBpm() {
		return minBpm;
	}
	
	/**
	 * @return moods
	 */
	public Set<Mood> getMoods() {
		return moods;
	}
	
	/**
	 * @return releases
	 */
	public Set<Release> getReleases() {
		return releases;
	}
	
	/**
	 * defines if the channel should consider the season
	 * 
	 * @param considerSeason
	 */
	public void considerSeason(boolean considerSeason) {
		this.considerSeason = considerSeason;
	}
	
	/**
	 * defines if the channel should consider the weather conditions
	 * 
	 * @param considerWeather
	 */
	public void considerWeather(boolean considerWeather) {
		this.considerWeather = considerWeather;
	}
	
	/**
	 * defines if the channel should consider the time of day
	 * 
	 * @param considerTimeOfDay
	 */
	public void considerTimeOfDay(boolean considerTimeOfDay) {
		this.considerTimeOfDay = considerTimeOfDay;
	}
	
	/**
	 * @return true if the channel considers the season, false otherwise
	 */
	public boolean isConsideringSeason() {
		return this.considerSeason;
	}
	
	/**
	 * @return true if the channel considers the weather conditions, false otherwise
	 */
	public boolean isConsideringWeather() {
		return considerWeather;
	}
	
	/**
	 * @return true if the channel considers the time of day, false otherwise
	 */
	public boolean isConsideringTimeOfDay() {
		return this.considerTimeOfDay;
	}
	
	/**
	 * @return playlist
	 */
	public Playlist getPlaylist() {
		return playlist;
	}
	
	/**
	 * creates a string with all information about the channel
	 * 
	 * @return string
	 */
	public String getInfo() {
		// releases
		String releases = "";
		for (Release release : getReleases()) {
			if (!releases.isEmpty()) {
				releases += ", ";
			}
			releases += release.toString();
		}
		
		// times of day, seasons, weather conditions
		String timeOfDay = considerTimeOfDay ? "yes" : "no";
		String season = considerSeason ? "yes" : "no";
		String weather = considerWeather ? "yes" : "no";
		
		// moods
		String moods = "";
		for (Mood mood : getMoods()) {
			if (!moods.isEmpty()) {
				moods += ", ";
			}
			moods += mood.toString();
		}

		// create message
		String message = "ID: " + getId()
				+ "\nLabel: " + getLabel()
				+ "\nImage: " + getImage()
				+ "\nReleases: " + releases
				+ "\nDuration: " + getDuration()
				+ "\nConsider time of day: " + timeOfDay
				+ "\nConsider season: " + season
				+ "\nConsider weather conditions: " + weather
				+ "\nMoods: " + moods;
		return message;
	}
	
	/**
	 * two channels are equal if they have the same id
	 * 
	 * @see Object#equals(Object)
	 */
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof Channel)) {
			return false;
		}
		return getId() == ((Channel) o).getId();
	}
	
	/**
	 * checks if a given track matches the channel attributes
	 * 
	 * @param _t
	 * @param currentTimeOfDay
	 * @param currentWeatherConditions
	 * @return true if the given track comes up to the channel attributes, false otherwise
	 */
	public boolean matches(Track _t, TimeOfDay currentTimeOfDay,
			Condition currentWeatherConditions) {
		boolean matchsDuration = maxDuration == 0
				|| _t.getDuration() <= maxDuration;
		boolean matchsBpm = minBpm == 0
				|| _t.getBpm() >= minBpm;
		boolean matchsReleases = releases.size() == 0
				|| releases.contains(Release.getByYear(_t.getRelease()));
		boolean matchsTimeOfDay = !isConsideringTimeOfDay()
				|| _t.getTimesOfDay().contains(currentTimeOfDay);
		boolean matchsWeatherConditions = !isConsideringWeather()
				|| _t.getWeatherConditions().contains(currentWeatherConditions);
		
		return matchsDuration && matchsBpm && matchsReleases && matchsTimeOfDay
				&& matchsWeatherConditions;
	}
}
